<?php
// +----------------------------------------------------------------------
// | INPHP
// | Copyright (c) 2023 https://inphp.cc All rights reserved.
// | Licensed ( https://opensource.org/licenses/MIT )
// | Author: 幺月儿(https://gitee.com/lulanyin) Email: inphp@qq.com
// +----------------------------------------------------------------------
// | 个人用户API
// +----------------------------------------------------------------------
namespace app\sso\http\api;

use app\sso\model\UserAuthModel;
use app\sso\model\UserModel;
use Inphp\Core\Db\Db;
use Inphp\Core\Middlewares;
use Inphp\Core\Modules;
use Inphp\Core\Object\Message;
use Inphp\Core\Util\Str;

#[\app\admin\attributes\auth] class user
{
    /**
     * UID
     * @var int
     */
    public int $uid = 0;

    /**
     * 账户数据
     * @var array
     */
    public array $user = [];

    /**
     * 登陆TOKEN
     * @var string
     */
    public string $token = "";

    /**
     * 获取授权账户信息
     * @return array
     */
    public function index(): array
    {
        return [
            "uid"           => $this->user["uid"],
            "parentUid"     => $this->user["parentUid"] ?? 0,
            "parentsUid"    => $this->user["parentsUid"] ?? null,
            "username"      => $this->user["username"] ?? null,
            "countryCode"   => $this->user["countryCode"] ?? 86,
            "phone"         => $this->user["phone"] ?? null,
            "nickname"      => $this->user["nickname"] ?? null,
            "face"          => $this->user["face"] ?? null,
            "registerTime"  => $this->user["registerTime"] ?? date("Y-m-d H:i:s"),
            "ip"            => $this->user["ip"] ?? null,
            "state"         => $this->user["state"] ?? 1,
            "admin"         => $this->user["admin"] ?? 0,
            "level"         => $this->user["level"] ?? 0,
            "thirdPartyList"=> !empty($this->user['thirdPartyList']) ? explode(",", $this->user['thirdPartyList']) : []
        ];
    }

    /**
     * 设置昵称
     * @return Message
     */
    public function setNickname(): Message
    {
        $nickname = POST("nickname");
        $nickname = !empty($nickname) ? Str::trim($nickname) : null;
        if (empty($nickname)) {
            return httpMessage('缺少昵称');
        }
        if (mb_strlen($nickname) < 2 || mb_strlen($nickname) > 30) {
            return httpMessage('昵称长度请控制在2~30个字符');
        }
        //可修改, 先检测是否重复
        $exists = UserModel::emptyQuery()
            ->where("uid", "!=", $this->uid)
            ->where("nickname", UserModel::encodeNickname($nickname))
            ->first();
        if (!empty($exists)) {
            return httpMessage('昵称已被使用');
        }
        $db = UserModel::emptyQuery()
            ->where("uid", $this->uid)
            ->set("nickname", UserModel::encodeNickname($nickname));
        if ($db->update()) {
            return httpMessage(0, '保存成功');
        }
        return httpMessage(40);
    }

    /**
     * 设置昵称
     * @return Message
     */
    public function setFace(): Message
    {
        $face = POST("face");
        $face = !empty($face) ? parseUploadFilesUrl($face) : null;
        if (empty($face)) {
            return httpMessage('缺少头像图片!');
        }
        $db = UserModel::emptyQuery()
            ->where("uid", $this->uid)
            ->set("face", $face);
        if ($db->update()) {
            return httpMessage(0, 'success');
        }
        return httpMessage(40);
    }

    /**
     * 设置昵称
     * @return Message
     */
    public function setPassword(): Message
    {
        $password = POST("password");
        $password = !empty($password) ? $password : null;
        if (empty($password)) {
            return httpMessage('缺少密码');
        }
        $type = POST("type");
        $type = $type == 'sp' ? 'sp' : 'password';
        if (strlen($password) < 6 || strlen($password) > 16) {
            return httpMessage("密码长度请控制在6~16个字符");
        }
        //需要手机SMS验证

        $smsCode = POST("smsCode");
        $smsCode = is_numeric($smsCode) && strlen($smsCode) === 6 ? $smsCode : null;
        if (empty($smsCode)) {
            return httpMessage(21);
        }
        if (!Str::isPhoneNumber($this->user["phone"], $this->user['countryCode'])) {
            return httpMessage("您还未绑定手机号，无法修改密码");
        }
        //校验短信验证码
        if (!\app\sso\lib\sms\SMS::verify($this->user['countryCode'], $this->user["phone"], $smsCode, \app\sso\lib\sms\SMS::ACT_AUTH)) {
            return httpMessage(21);
        }
        $db = UserModel::emptyQuery()->where("uid", $this->uid);
        if ($type == "password") {
            list($password, $pwdKey) = UserModel::hashLoginPassword($password);
            $db->set([
                "password"      => $password,
                "pwdKey"        => $pwdKey
            ]);
        } else {
            $db->set("sp", UserModel::hashSP($password, $this->uid));
        }
        if ($db->update()) {
            return httpMessage(0, 'success');
        }
        return httpMessage(40);
    }

    /**
     * 绑定手机，如果已绑定，必须提供旧的手机验证码
     * @return Message
     */
    public function setPhone(): Message
    {
        $countryCode = POST("countryCode", 86);
        $countryCode = is_numeric($countryCode) && $countryCode >= 0 ? $countryCode : 86;
        $phone = POST("phone");
        $phone = !empty($phone) && Str::isPhoneNumber($phone, $countryCode) ? $phone : null;
        if (empty($phone)) {
            return httpMessage("手机号码格式错误");
        }
        //查询是否重复
        $exists = UserModel::emptyQuery()
            ->where("countryCode", $countryCode)
            ->where("phone", $phone)
            ->first();
        if (!empty($exists)) {
            return httpMessage("手机号码已被使用");
        }
        $smsCode = POST("smsCode");
        $smsCode = is_numeric($smsCode) && strlen($smsCode) === 6 ? $smsCode : null;
        if (empty($smsCode)) {
            return httpMessage(20);
        }
        //检测是否已绑定有手机
        if (!empty($this->user["phone"]) && Str::isPhoneNumber($this->user["phone"], $this->user["countryCode"] ?? 86)) {
            $oldSmsCode = POST("oldSmsCode");
            $oldSmsCode = is_numeric($oldSmsCode) && strlen($oldSmsCode) === 6 ? $oldSmsCode : null;
            if (empty($oldSmsCode)) {
                return httpMessage('缺少原绑定手机的验证码');
            }
            if ($countryCode == $this->user["countryCode"] && $phone == $this->user["phone"]) {
                return httpMessage("新旧手机号码一致，无需处理");
            }
            if (!\app\sso\lib\sms\SMS::verify($this->user["countryCode"], $this->user["phone"], $oldSmsCode, \app\sso\lib\sms\SMS::ACT_AUTH)) {
                return httpMessage("原绑定手机的验证码错误");
            }
        }
        if (!\app\sso\lib\sms\SMS::verify($countryCode, $phone, $smsCode, \app\sso\lib\sms\SMS::ACT_AUTH)) {
            return httpMessage("新绑定手机的验证码错误");
        }
        $db = UserModel::emptyQuery()
            ->where("uid", $this->uid)
            ->set([
                "countryCode"       => $countryCode,
                "phone"             => $phone
            ]);
        if ($db->update()) {
            Middlewares::process("sso.user.phone.change", [
                "uid"   => $this->uid,
                "phone" => $phone
            ]);
            return httpMessage(0, "更换手机号码完成");
        }
        return httpMessage("更换手机号码失败，请稍后再试");
    }

    /**
     * 绑定第三方平台，强制使用自动授权即可
     * @return Message
     */
    public function bind(): Message
    {
        //支持第三方插件授权
        $plugin = POST("plugin");
        $name = !empty($plugin) ? Str::trim($plugin) : null;
        $name = !empty($name) ? Str::trim($name) : null;
        if (empty($name)) {
            //插件不存在
            return httpMessage("缺少授权插件名称参数");
        }
        //检测插件是否存在
        $controller = join("\\", ['app\sso\thirdParty', $name, 'auth']);
        if (!class_exists($controller)) {
            return httpMessage("无法处理该授权请求，没有该类型的授权插件");
        }
        //触发方法处理
        if (method_exists($controller, "process")) {
            //
            $result = $controller::process(null, ['bind' => true, 'uid' => $this->uid]);
            if ($result instanceof Message) {
                if ($result->error === 0) {
                    //更新已绑定第三方字段
                    $thirdPartyList = $this->user['thirdPartyList'] ?? "";
                    @UserModel::emptyQuery()
                        ->where("uid", $this->uid)
                        ->set("thirdPartyList", !empty($thirdPartyList) ? "{$thirdPartyList},{$name}" : $name)
                        ->update();
                }
                return $result;
            }
        }
        return httpMessage("未知处理");
    }

    /**
     * 解绑第三方平台
     * @return Message
     */
    public function unbind(): Message
    {
        //支持第三方插件授权
        $plugin = POST("plugin");
        $name = !empty($plugin) ? Str::trim($plugin) : null;
        $name = !empty($name) ? Str::trim($name) : null;
        if (empty($name)) {
            //插件不存在
            return httpMessage("缺少授权插件名称参数");
        }
        //检测插件是否存在
        $controller = join("\\", ['app\sso\thirdParty', $name, 'unbind']);
        if (!class_exists($controller)) {
            return httpMessage("无法处理该授权请求，没有该类型的授权插件");
        }
        //触发方法处理
        if (method_exists($controller, "process")) {
            //
            $result = $controller::process(null, ['uid' => $this->uid]);
            if ($result instanceof Message) {
                if ($result->error === 0) {
                    //更新已绑定第三方字段
                    $thirdPartyList = $this->user['thirdPartyList'] ?? "";
                    $thirdPartyList = !empty($thirdPartyList) ? explode(",", $thirdPartyList) : [];
                    if (in_array($name, $thirdPartyList)) {
                        $values = [];
                        foreach ($thirdPartyList as $val) {
                            if ($val != $name) {
                                $values[] = $val;
                            }
                        }
                        @UserModel::emptyQuery()
                            ->where("uid", $this->uid)
                            ->set("thirdPartyList", join(",", $values))
                            ->update();
                    }
                }
                return $result;
            }
        }
        return httpMessage("未知处理");
    }

    public function bindDetail(): Message
    {
        //支持第三方插件授权
        $plugin = POST("plugin");
        $name = !empty($plugin) ? Str::trim($plugin) : null;
        $name = !empty($name) ? Str::trim($name) : null;
        if (empty($name)) {
            //插件不存在
            return httpMessage("缺少授权插件名称参数");
        }
        //检测插件是否存在
        $controller = join("\\", ['app\sso\thirdParty', $name, 'bind']);
        if (!class_exists($controller)) {
            return httpMessage("无法处理该授权请求，没有该类型的授权插件");
        }
        //触发方法处理
        if (method_exists($controller, "detail")) {
            $result = $controller::detail(null, ['uid' => $this->uid]);
            if ($result instanceof Message) {
                return $result;
            }
        }
        return httpMessage("无法处理");
    }

    public function logout(): Message
    {
        UserAuthModel::dropToken($this->token);
        return httpMessage(0, "账户已注销登陆状态");
    }

    public function qwkf(): Message
    {
        $qwkf = Modules::getModule("sso")->getConfig("qwkf");
        $qwkf = is_array($qwkf) ? $qwkf : ["appid" => "", "url" => ""];
        $row = Db::from("sso_userQWKF")->where("uid", $this->uid)->first();
        $row = !empty($row) ? $row : ["appid" => '', 'url' => ''];
        $row["appid"] = $qwkf["appid"];
        return httpMessage($row);
    }
    public function setQWKF(): Message
    {
        $appid = POST("appid");
        $appid = !empty($appid) ? Str::trim($appid) : null;
        if (empty($appid)) {
            //return httpMessage("缺少企业微信APPID");
        }
        $url = POST("url");
        $url = !empty($url) ? Str::trim($url) : null;
        $url = !empty($url) && stripos($url, "https://work.weixin.qq.com/kfid/") === 0 ? $url : null;
        if (empty($url)) {
            return httpMessage("客服链接格式无效");
        }
        //存在则保存，不存在则创建
        $exists = Db::from("sso_userQWKF")->where("uid", $this->uid)->first();
        $data = [
            "appid" => $appid ?? 'null',
            "url" => $url
        ];
        $method = "insert";
        $db = Db::from("sso_userQWKF");
        if (!empty($exists)) {
            $method = "update";
            $db->where("uid", $this->uid);
        } else {
            $data["uid"] = $this->uid;
        }
        if ($db->{$method}($data)) {
            return httpMessage(0, "保存成功");
        }
        return httpMessage("保存失败，请稍后再试");
    }
}